package com.sucsoft.pdf.service;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.sucsoft.pdf.bean.mongodb.AllPageInfo;
import com.sucsoft.pdf.bean.mongodb.CatalogInfo;
import com.sucsoft.pdf.bean.mongodb.ChildCatalog;
import com.sucsoft.pdf.bean.mongodb.PageInfo;
import com.sucsoft.pdf.utils.HelpUtil;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * @author jinly
 * @date 2020/10/23
 */
@Service
public class SpiltService {

    @Autowired
    private MongoTemplate mongoTemplate;

    //文件位置
    @Value("${file.path:D:/upload/file/}")
    private String filePath;
    //文件夹前缀
    @Value("${file.prefix:/file}")
    private String filePrefix;


    public void spiltPdf(String bookId, String bookUrl, String bookName) throws Exception {
        if (!bookUrl.endsWith(".pdf")) {
            throw new Exception("不是pdf文件");
        }
        if (bookUrl.startsWith(filePrefix)) {
            bookUrl = bookUrl.substring(filePrefix.length());
        }
        String pdfFilePath = filePath + bookUrl;
        //保存文件路径
        String savePath = "";
        int dot = pdfFilePath.lastIndexOf('.');
        if ((dot > -1) && (dot < (pdfFilePath.length()))) {
            savePath = pdfFilePath.substring(0, dot);
        }
        splitPDFOneByOne(pdfFilePath, savePath, bookId, bookName);
    }

    /**
     * //     * @param path       源PDF路径
     * //     * @param fileName   源PDF文件名
     *
     * @param outputPath 拆分后输出的PDF路径
     * @param bookId
     * @Param pathUrl  文件路径
     * @author Reverse_XML
     * 把PDF 按页(逐页、单页)拆分(一页一页拆分，一页为一个新PDF文件)
     */
    public void splitPDFOneByOne(String pathUrl, String outputPath, String bookId, String bookName) {
        String sep = java.io.File.separator;
        PdfReader reader = null;
        int numberOfPages = 0;
        try {
            AllPageInfo allPageInfo = new AllPageInfo();
            allPageInfo.setId(bookId);
            allPageInfo.setBookId(bookId);
//            reader = new PdfReader(path + sep + fileName);
            reader = new PdfReader(pathUrl);
            //获取目录结构
            getBookMark(reader, bookId, bookName);
            numberOfPages = reader.getNumberOfPages();
            File filePath = new File(outputPath);
            if (!filePath.exists()) {
                filePath.mkdirs();
            }
            //切成单页jpg文件
            List<String> list = pdfPathToImagePaths(pathUrl, outputPath);
            //切成单页pdf
            for (int i = 1; i <= numberOfPages; i++) {
                Document document = null;
                PdfCopy copy = null;
                try {
                    document = new Document(reader.getPageSize(1));
                    Rectangle pageSize = reader.getPageSize(1);
                    String textFromPage = PdfTextExtractor.getTextFromPage(reader, i);
                    float height = pageSize.getHeight();
                    float width = pageSize.getWidth();
                    String savePath = outputPath + sep + (i - 1) + ".pdf";
                    //fileName.substring(0, fileName.lastIndexOf(".")) + "_" + (i-1) + ".pdf";
                    try {
                        copy = new PdfCopy(document, new FileOutputStream(savePath));
                    } catch (DocumentException e) {
                        e.printStackTrace();
                    }
                    document.open();
                    document.newPage();
                    PdfImportedPage page = copy.getImportedPage(reader, i);
                    copy.addPage(page);
                    //组装mongodb对象
                    buildPageInfo(allPageInfo, i, Double.valueOf(String.valueOf(height)), Double.valueOf(String.valueOf(width)), savePath, list.get(i - 1), textFromPage);
                } finally {
                    if (document != null)
                        document.close();
                    if (copy != null)
                        copy.close();
                }
            }
            //保存每页信息到mongo
            mongoTemplate.save(allPageInfo);
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } catch (DocumentException e) {
            System.out.println(e.getMessage());
        } finally {
            if (reader != null)
                reader.close();
        }
    }

    /**
     * png文件路径
     *
     * @param pdfPath    pdf完整路径
     * @param outputPath 输出路径
     * @return png集合
     */
    private List<String> pdfPathToImagePaths(String pdfPath, String outputPath) throws IOException {
        File pdfFile = new File(pdfPath);
        PDDocument pdDocument = PDDocument.load(pdfFile);
        int pageCount = pdDocument.getNumberOfPages();
        PDFRenderer pdfRenderer = new PDFRenderer(pdDocument);
        List<String> imagePathList = new ArrayList<>();
        for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
            String imgPath = outputPath + File.separator + pageIndex + ".png";
            BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, 72, ImageType.RGB);
            System.out.println(image.getHeight());
            System.out.println(image.getWidth());
            ImageIO.write(image, "png", new File(imgPath));
            imagePathList.add(imgPath);
        }
        pdDocument.close();
        return imagePathList;
    }

    /**
     * 获取目录列表
     *
     * @param pdfReader
     */
    private void getBookMark(PdfReader pdfReader, String bookId, String bookName) {
        CatalogInfo catalogInfo = new CatalogInfo();
        catalogInfo.setBookId(bookId);
        catalogInfo.setId(bookId);
        catalogInfo.setBookName(bookName);
        catalogInfo.setTotalPage(pdfReader.getNumberOfPages());
        List<HashMap<String, Object>> list = SimpleBookmark.getBookmark(pdfReader);
        if (list != null) {
            list.forEach(it -> {
                if (it.get("Page") != null) {
                    int j = 1;
                    ChildCatalog childCatalog = new ChildCatalog();
                    //层级
                    childCatalog.setCatalogLevel(j);
                    //目录id
                    childCatalog.setCatalogId(HelpUtil.generateId());
                    childCatalog.setCatalogName(it.get("Title") == null ? "" : it.get("Title").toString());
                    //获取目录 所在 文件 位置
                    String pagePosition = it.get("Page").toString();
                    showBookmark(it, j, childCatalog);
                    getPosition(childCatalog, pagePosition);
                    catalogInfo.getChildCatalogList().add(childCatalog);
                }

            });
        }
        //保存目录信息到mongo
        mongoTemplate.save(catalogInfo);
    }

    /**
     * @param bookmark 目录
     * @param level    层级
     * @return
     */
    private ChildCatalog showBookmark(HashMap<String, Object> bookmark, int level, ChildCatalog catalog) {
        //子目录
        ChildCatalog childCatalog = new ChildCatalog();
        //不是第一层级的才新增
        if (level != 1) {
            if(bookmark.get("Page") != null){
                childCatalog.setCatalogName(bookmark.get("Title") != null ? bookmark.get("Title").toString() : "");
                childCatalog.setCatalogId(HelpUtil.generateId());
                childCatalog.setCatalogLevel(level);
                String pagePosition = bookmark.get("Page").toString();
                getPosition(childCatalog, pagePosition);
                catalog.getChildCatalogList().add(childCatalog);
            }
        } else {
            childCatalog = catalog;
        }
        ArrayList kids = (ArrayList) bookmark.get("Kids");
        if (kids != null) {
            level++;
            int finalLevel = level;
            ChildCatalog finalChildCatalog = childCatalog;
            kids.forEach(it -> showBookmark((HashMap<String, Object>) it, finalLevel, finalChildCatalog));
        }
        return catalog;
    }

    /**
     * 获取目录所在 文件位置
     *
     * @param childCatalog 目录记录行
     * @param pagePosition 目录在页面中的位置
     */
    private void getPosition(ChildCatalog childCatalog, String pagePosition) {
        //页码数据位置
        //34 XYZ 365.35 161.9 0
        String[] s = pagePosition.split(" ");
        //解析出页码
        childCatalog.setPageNum(Integer.valueOf(s[0]));
        //解析出 y 轴坐标
        childCatalog.setPosition(Double.parseDouble(s[3]));

    }

    private void buildPageInfo(AllPageInfo allPageInfo, Integer pageNum, Double height, Double width, String pdfUrl, String imgUrl, String content) {
        //pdf存储路径
        pdfUrl = pdfUrl.replaceFirst(filePath, "");
        pdfUrl = filePrefix + pdfUrl;
        //img路径
        imgUrl = imgUrl.replaceFirst(filePath, "");
        imgUrl = filePrefix + imgUrl;
        //存每页的信息
        PageInfo pageInfo = new PageInfo(pageNum, height, width, pdfUrl, imgUrl, content);
        pageInfo.setPageId(HelpUtil.generateId());
        allPageInfo.getPageInfoList().add(pageInfo);
    }


}
